`include "ascon_define.v"
`define ADDR_W 10
module `ASCON_AEAD_CTRL_REGS
(
    input                                        ascon_aead_clk_i,
    input                                        ascon_aead_rst_n_i,
//总线访问信号
    input                                        ascon_aead_ctrl_regs_en_i,
    input                                        ascon_aead_ctrl_regs_wen_i,
    input                      [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_addr_i,
    input                      [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_wdata_i,

    output                     [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_rdata_o,
//状态机访问信号
    input                                        ascon_aead_ctrl_regs_prot_i,  //保护信号，高电平期间，寄存器无法被写
    input                                        ascon_aead_ctrl_regs_fsm_sta_wen_i, //状态机写z状态寄存器写使能信号
    input                                        ascon_aead_ctrl_regs_fsm_en_wen_i, //状态机写使能寄存器写使能信号
    input                                        ascon_aead_ctrl_regs_w_t_wen_i,  //状态机写使能寄存器摘要寄存器信号
    input                      [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_w_sta_i, //状态寄存器数据
    input                      [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_w_en_i,  //使能寄存器数据
    input                             [`T_W-1:0] ascon_aead_ctrl_regs_w_t_i,  //摘要寄存器数据
//输出配置信号
    output                     [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_msg_block_num_o,
    output                     [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_msg_addr_o,
    output                     [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_aead_ctrl_sta_o,
    output                                       ascon_aead_ctrl_regs_aead_ctrl_en_o,
    output                                       ascon_aead_ctrl_regs_aead_ctrl_mode_o,
    output                     [`CTRL_REG_W-1:0] ascon_aead_ctrl_regs_aead_c_addr_o,
    output                            [`A_W-1:0] ascon_aead_ctrl_regs_aead_a_o,
    output                            [`K_W-1:0] ascon_aead_ctrl_regs_aead_k_o,
    output                            [`N_W-1:0] ascon_aead_ctrl_regs_aead_n_o
);
//接口信号
wire                                             reg_en_p;
wire                                             wen_p;
wire                               [`ADDR_W-1:0] addr_p;
wire                           [`CTRL_REG_W-1:0] wdata_p;
reg                            [`CTRL_REG_W-1:0] rdata_p;
wire                                             prot_p;
wire                                             fsm_sta_wen_p;
wire                                             fsm_en_wen_p;
wire                                             fsm_t_wen_p;
wire                           [`CTRL_REG_W-1:0] w_sta_p;
wire                           [`CTRL_REG_W-1:0] w_en_p;
wire                                  [`T_W-1:0] w_t_p;

//寄存器信号
reg                            [`CTRL_REG_W-1:0] msg_block_num;

reg                            [`CTRL_REG_W-1:0] msg_addr;
reg                            [`CTRL_REG_W-1:0] aead_ctrl_sta;
reg                            [`CTRL_REG_W-1:0] aead_ctrl_en;
reg                            [`CTRL_REG_W-1:0] aead_ctrl_mode;
reg                            [`CTRL_REG_W-1:0] aead_c_addr;
reg                            [`CTRL_REG_W-1:0] aead_a_lw;
reg                            [`CTRL_REG_W-1:0] aead_a_hw;
reg                            [`CTRL_REG_W-1:0] aead_k_w0;
reg                            [`CTRL_REG_W-1:0] aead_k_w1;
reg                            [`CTRL_REG_W-1:0] aead_k_w2;
reg                            [`CTRL_REG_W-1:0] aead_k_w3;
reg                            [`CTRL_REG_W-1:0] aead_n_w0;
reg                            [`CTRL_REG_W-1:0] aead_n_w1;
reg                            [`CTRL_REG_W-1:0] aead_n_w2;
reg                            [`CTRL_REG_W-1:0] aead_n_w3;
reg                            [`CTRL_REG_W-1:0] aead_t_w0;
reg                            [`CTRL_REG_W-1:0] aead_t_w1;
reg                            [`CTRL_REG_W-1:0] aead_t_w2;
reg                            [`CTRL_REG_W-1:0] aead_t_w3;

wire                                             msg_addr_en;
wire                                             msg_block_num_en;
wire                                             aead_ctrl_sta_en;
wire                                             aead_ctrl_en_en;
wire                                             aead_ctrl_mode_en;
wire                                             aead_c_addr_en;
wire                                             aead_a_lw_en;
wire                                             aead_a_hw_en;
wire                                             aead_k_w0_en;
wire                                             aead_k_w1_en;
wire                                             aead_k_w2_en;
wire                                             aead_k_w3_en;
wire                                             aead_n_w0_en;
wire                                             aead_n_w1_en;
wire                                             aead_n_w2_en;
wire                                             aead_n_w3_en;

wire                                             msg_addr_ren;
wire                                             msg_block_num_ren;
wire                                             aead_ctrl_sta_ren;
wire                                             aead_ctrl_en_ren;
wire                                             aead_ctrl_mode_ren;
wire                                             aead_c_addr_ren;
wire                                             aead_a_lw_ren;
wire                                             aead_a_hw_ren;
wire                                             aead_k_w0_ren;
wire                                             aead_k_w1_ren;
wire                                             aead_k_w2_ren;
wire                                             aead_k_w3_ren;
wire                                             aead_n_w0_ren;
wire                                             aead_n_w1_ren;
wire                                             aead_n_w2_ren;
wire                                             aead_n_w3_ren;

//接口信号连接

assign reg_en_p         = ascon_aead_ctrl_regs_en_i;
assign wen_p            = ascon_aead_ctrl_regs_wen_i;
assign addr_p           = ascon_aead_ctrl_regs_addr_i;
assign wdata_p          = ascon_aead_ctrl_regs_wdata_i;
assign prot_p           = ascon_aead_ctrl_regs_prot_i;
assign fsm_sta_wen_p    = ascon_aead_ctrl_regs_fsm_sta_wen_i;
assign fsm_en_wen_p     = ascon_aead_ctrl_regs_fsm_en_wen_i;
assign fsm_t_wen_p      = ascon_aead_ctrl_regs_w_t_wen_i;
assign w_sta_p          = ascon_aead_ctrl_regs_w_sta_i;
assign w_en_p           = ascon_aead_ctrl_regs_w_en_i;
assign w_t_p            = ascon_aead_ctrl_regs_w_t_i;

assign ascon_aead_ctrl_regs_rdata_o         = rdata_p;

assign ascon_aead_ctrl_regs_msg_block_num_o = msg_block_num;
assign ascon_aead_ctrl_regs_msg_addr_o      = msg_addr;
assign ascon_aead_ctrl_regs_aead_ctrl_sta_o = aead_ctrl_sta;
assign ascon_aead_ctrl_regs_aead_ctrl_en_o  = aead_ctrl_en[0];
assign ascon_aead_ctrl_regs_aead_ctrl_mode_o= aead_ctrl_mode[0];
assign ascon_aead_ctrl_regs_aead_c_addr_o   = aead_c_addr;
assign ascon_aead_ctrl_regs_aead_a_o        = {aead_a_hw,aead_a_lw};
assign ascon_aead_ctrl_regs_aead_k_o        = {aead_k_w3,aead_k_w2,aead_k_w1,aead_k_w0};
assign ascon_aead_ctrl_regs_aead_n_o        = {aead_n_w3,aead_n_w2,aead_n_w1,aead_n_w0};

//内部信号产生
assign msg_block_num_en = (addr_p == `ADDR_W'h00 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign msg_addr_en      = (addr_p == `ADDR_W'h04 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_ctrl_sta_en = (addr_p == `ADDR_W'h08 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_ctrl_en_en  = (addr_p == `ADDR_W'h0c && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_ctrl_mode_en= (addr_p == `ADDR_W'h10 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_c_addr_en   = (addr_p == `ADDR_W'h14 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_a_lw_en     = (addr_p == `ADDR_W'h18 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_a_hw_en     = (addr_p == `ADDR_W'h1c && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_k_w0_en     = (addr_p == `ADDR_W'h20 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_k_w1_en     = (addr_p == `ADDR_W'h24 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_k_w2_en     = (addr_p == `ADDR_W'h28 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_k_w3_en     = (addr_p == `ADDR_W'h2c && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_n_w0_en     = (addr_p == `ADDR_W'h30 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_n_w1_en     = (addr_p == `ADDR_W'h34 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_n_w2_en     = (addr_p == `ADDR_W'h38 && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;
assign aead_n_w3_en     = (addr_p == `ADDR_W'h3c && reg_en_p == 1'b1 && prot_p == 1'b0) ? 1'b1 : 1'b0;

assign msg_block_num_ren= (addr_p == `ADDR_W'h00 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign msg_addr_ren     = (addr_p == `ADDR_W'h04 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_ctrl_sta_ren= (addr_p == `ADDR_W'h08 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_ctrl_en_ren = (addr_p == `ADDR_W'h0c && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_ctrl_mode_ren= (addr_p == `ADDR_W'h10 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_c_addr_ren  = (addr_p == `ADDR_W'h14 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_a_lw_ren    = (addr_p == `ADDR_W'h18 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_a_hw_ren    = (addr_p == `ADDR_W'h1c && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_k_w0_ren    = (addr_p == `ADDR_W'h20 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_k_w1_ren    = (addr_p == `ADDR_W'h24 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_k_w2_ren    = (addr_p == `ADDR_W'h28 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_k_w3_ren    = (addr_p == `ADDR_W'h2c && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_n_w0_ren    = (addr_p == `ADDR_W'h30 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_n_w1_ren    = (addr_p == `ADDR_W'h34 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_n_w2_ren    = (addr_p == `ADDR_W'h38 && reg_en_p == 1'b1) ? 1'b1 : 1'b0;
assign aead_n_w3_ren    = (addr_p == `ADDR_W'h3c && reg_en_p == 1'b1) ? 1'b1 : 1'b0;

assign aead_t_w0_en     = fsm_t_wen_p;
assign aead_t_w1_en     = fsm_t_wen_p;
assign aead_t_w2_en     = fsm_t_wen_p;
assign aead_t_w3_en     = fsm_t_wen_p;

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : MSG_BLOCK_NUM_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    msg_block_num       <= `CTRL_REG_W'b0;
  else if (msg_block_num_en == 1'b1 && wen_p == 1'b1)
    msg_block_num       <= wdata_p;
  else
    msg_block_num       <= msg_block_num;
end
//指定待加密消息存储在缓存的地址
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : MSG_ADDR_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    msg_addr            <= `CTRL_REG_W'b0;
  else if (msg_addr_en == 1'b1 && wen_p == 1'b1)
    msg_addr            <= wdata_p;
  else
    msg_addr            <= msg_addr;
end
//状态寄存器：
//[7：0]：状态机状态编号
//为80000000代表运算完成
//为04000000代表等待下一笔数据写入
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_CTRL_STA_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_ctrl_sta       <= `CTRL_REG_W'b0;
  else if (fsm_sta_wen_p == 1'b1)
    aead_ctrl_sta       <= w_sta_p;
  else if (aead_ctrl_sta_en == 1'b1 && wen_p == 1'b1)
    aead_ctrl_sta       <= wdata_p;
  else
    aead_ctrl_sta       <= aead_ctrl_sta;
end
//算法使能寄存器：
//[0]：1使能 0失能
//等待下一笔写入的过程中要再次使能该寄存器
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin :AEAD_CTRL_EN_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_ctrl_en        <= `CTRL_REG_W'b0;
  else if (fsm_en_wen_p == 1'b1)
    aead_ctrl_en        <= w_en_p;
  else if (aead_ctrl_en_en == 1'b1 && wen_p == 1'b1)
    aead_ctrl_en        <= wdata_p;
  else
    aead_ctrl_en        <= aead_ctrl_en;
end
//设定工作模式
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : HASH_CTRL_MODE_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_ctrl_mode      <= `CTRL_REG_W'b0;
  else if (aead_ctrl_mode_en == 1'b1 && wen_p == 1'b1)
    aead_ctrl_mode      <= wdata_p;
  else
    aead_ctrl_mode      <= aead_ctrl_mode;
end
//设定密文存储在缓存的地址
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : HASH_C_ADDR_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_c_addr         <= `CTRL_REG_W'b0;
  else if (aead_c_addr_en == 1'b1 && wen_p == 1'b1)
    aead_c_addr         <= wdata_p;
  else
    aead_c_addr         <= aead_c_addr;
end
//关联信息寄存器组
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_A_LW_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_a_lw           <= `CTRL_REG_W'b0;
  else if (aead_a_lw_en == 1'b1 && wen_p == 1'b1)
    aead_a_lw           <= wdata_p;
  else
    aead_a_lw           <= aead_a_lw;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_A_HW_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_a_hw           <= `CTRL_REG_W'b0;
  else if (aead_a_hw_en == 1'b1 && wen_p == 1'b1)
    aead_a_hw           <= wdata_p;
  else
    aead_a_hw           <= aead_a_hw;
end
//密钥寄存器组
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_K_W0_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_k_w0           <= `CTRL_REG_W'b0;
  else if (aead_k_w0_en == 1'b1 && wen_p == 1'b1)
    aead_k_w0           <= wdata_p;
  else
    aead_k_w0           <= aead_k_w0;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_K_W1_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_k_w1           <= `CTRL_REG_W'b0;
  else if (aead_k_w1_en == 1'b1 && wen_p == 1'b1)
    aead_k_w1           <= wdata_p;
  else
    aead_k_w1           <= aead_k_w1;
end
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_K_W2_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_k_w2           <= `CTRL_REG_W'b0;
  else if (aead_k_w2_en == 1'b1 && wen_p == 1'b1)
    aead_k_w2           <= wdata_p;
  else
    aead_k_w2           <= aead_k_w2;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_K_W3_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_k_w3           <= `CTRL_REG_W'b0;
  else if (aead_k_w3_en == 1'b1 && wen_p == 1'b1)
    aead_k_w3           <= wdata_p;
  else
    aead_k_w3           <= aead_k_w3;
end

//随机数寄存器组
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_N_W0_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_n_w0           <= `CTRL_REG_W'b0;
  else if (aead_n_w0_en == 1'b1 && wen_p == 1'b1)
    aead_n_w0           <= wdata_p;
  else
    aead_n_w0           <= aead_n_w0;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_N_W1_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_n_w1           <= `CTRL_REG_W'b0;
  else if (aead_n_w1_en == 1'b1 && wen_p == 1'b1)
    aead_n_w1           <= wdata_p;
  else
    aead_n_w1           <= aead_n_w1;
end
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_N_W2_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_n_w2           <= `CTRL_REG_W'b0;
  else if (aead_n_w2_en == 1'b1 && wen_p == 1'b1)
    aead_n_w2           <= wdata_p;
  else
    aead_n_w2           <= aead_n_w2;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_N_W3_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_n_w3           <= `CTRL_REG_W'b0;
  else if (aead_n_w3_en == 1'b1 && wen_p == 1'b1)
    aead_n_w3           <= wdata_p;
  else
    aead_n_w3           <= aead_n_w3;
end

//摘要寄存器组
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_T_W0_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_t_w0           <= `CTRL_REG_W'b0;
  else if (aead_t_w0_en == 1'b1)
    aead_t_w0           <= w_t_p[32-1:0];
  else
    aead_t_w0           <= aead_t_w0;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_T_W1_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_t_w1           <= `CTRL_REG_W'b0;
  else if (aead_t_w1_en == 1'b1)
    aead_t_w1           <= w_t_p[64-1:32];
  else
    aead_t_w1           <= aead_t_w1;
end
always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_T_W2_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_t_w2           <= `CTRL_REG_W'b0;
  else if (aead_t_w2_en == 1'b1)
    aead_t_w2           <= w_t_p[96-1:64];
  else
    aead_t_w2           <= aead_t_w2;
end

always @(posedge ascon_aead_clk_i or negedge ascon_aead_rst_n_i)
begin : AEAD_T_W3_PROG
  if (ascon_aead_rst_n_i == 1'b0)
    aead_t_w3           <= `CTRL_REG_W'b0;
  else if (aead_t_w3_en == 1'b1)
    aead_t_w3           <= w_t_p[128-1:96];
  else
    aead_t_w3           <= aead_t_w3;
end


always @(*)
begin : RDATA_P_PROG
  if (wen_p == 1'b0)
  begin
    if (msg_addr_ren == 1'b1)
      rdata_p           = msg_addr;
    else if (msg_block_num_ren == 1'b1)
      rdata_p           = msg_block_num;
    else if (aead_ctrl_sta_ren == 1'b1)
      rdata_p           = aead_ctrl_sta;
    else if (aead_ctrl_en_ren == 1'b1)
      rdata_p           = aead_ctrl_en;
    else if (aead_ctrl_mode_ren == 1'b1)
      rdata_p           = aead_ctrl_mode;
    else if (aead_c_addr_ren == 1'b1)
      rdata_p           = aead_c_addr;
    else if (aead_a_lw_ren == 1'b1)
      rdata_p           = aead_a_lw;
    else if (aead_a_hw_ren == 1'b1)
      rdata_p           = aead_a_hw;
    else if (aead_k_w0_ren == 1'b1)
      rdata_p           = aead_k_w0;
    else if (aead_k_w1_ren == 1'b1)
      rdata_p           = aead_k_w1;
    else if (aead_k_w2_ren == 1'b1)
      rdata_p           = aead_k_w2;
    else if (aead_k_w3_ren == 1'b1)
      rdata_p           = aead_k_w3;
    else if (aead_n_w0_ren == 1'b1)
      rdata_p           = aead_n_w0;
    else if (aead_n_w1_ren == 1'b1)
      rdata_p           = aead_n_w1;
    else if (aead_n_w2_ren == 1'b1)
      rdata_p           = aead_n_w2;
    else if (aead_n_w3_ren == 1'b1)
      rdata_p           = aead_n_w3;
    else if (aead_t_w0_en == 1'b1)
      rdata_p           = aead_t_w0;
    else if (aead_t_w1_en == 1'b1)
      rdata_p           = aead_t_w1;
    else if (aead_t_w2_en == 1'b1)
      rdata_p           = aead_t_w2;
    else if (aead_t_w3_en == 1'b1)
      rdata_p           = aead_t_w3;
    else
      rdata_p           = `CTRL_REG_W'b0;
  end
  else
    rdata_p             = `CTRL_REG_W'b0;
end

endmodule